﻿using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Reflection;
using System.Windows.Forms;
using Emgu.CV;
using Emgu.CV.Structure;

namespace CellImageProcessing
{
    public partial class Form_Main : Form
    {
        #region Global
        
        Image<Bgr, Byte> backgroundColor;

        int showedImage = 0;    // mark the image which is being displayed: 00000000
        
        CellData mainCellData;  // cellData which is being processed
        CellData miniCellData;  // cellData which is dropped from the main cellData

        int backgroundGrayThres; // background gray value
        
        // area that is chosen
        Point p1 = new Point();
        Point p2 = new Point();

        #endregion Global

        public Form_Main()
        {
            InitializeComponent();
            showedImage = 0;           
        }

        private void openToolStripMenuItem_Click(object sender, EventArgs e)
        {
            DialogResult dlgResult = this.openFileDialog_Main.ShowDialog();
            if (dlgResult == DialogResult.OK)
            {
                string file = this.openFileDialog_Main.FileName;
                try
                {
                    //processedImage = new Image<Bgr, byte>(file);
                    //processedImage = processedImage.Resize(pictureBox_Main.Width, pictureBox_Main.Height, Emgu.CV.CvEnum.INTER.CV_INTER_LINEAR);
                    //this.pictureBox_Main.Image = processedImage.Bitmap;

                    mainCellData = new CellData();
                    mainCellData.Initialize(file);
                    this.pictureBox_Main.Image = mainCellData.rgbImage.Bitmap;
                    miniCellData = new CellData();
                    showedImage &= 0;
                    showedImage |= 1;

                    p1 = new Point(0, 0);
                    p2 = new Point(0, 0);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.ToString());
                }
            }
        }

        private void saveToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (this.saveFileDialog_Main.ShowDialog() == DialogResult.OK)
            {
            }
        }

        private void pictureBox_Main_MouseClick(object sender, MouseEventArgs e)
        {
            if (mainCellData != null)
            {
                Byte[] tempByte = BitConverter.GetBytes(showedImage);
                BitArray tempBits = new BitArray(tempByte);
                Bgr tempBgr = new Bgr();
                double tempGray = 0;

                for (int i = 0; i < 8; i++)
                {
                    if (tempBits[i] == true)
                    {
                        switch (i)
                        {
                            case 0:
                                tempBgr = mainCellData.rgbImage[e.Y, e.X];
                                break;
                            case 1:
                                tempGray = mainCellData.grayImage[e.Y, e.X].Intensity;
                                tempBgr = new Bgr(tempGray, tempGray, tempGray);
                                break;
                            case 2:
                                tempGray = mainCellData.binaryImage[e.Y, e.X].Intensity;
                                tempBgr = new Bgr(tempGray, tempGray, tempGray);
                                break;
                            case 3:
                                tempGray = mainCellData.edgeImage[e.Y, e.X].Intensity;
                                tempBgr = new Bgr(tempGray, tempGray, tempGray);
                                break;
                            case 4:
                                tempGray = mainCellData.gridImage[e.Y, e.X].Intensity;
                                tempBgr = new Bgr(tempGray, tempGray, tempGray);
                                break;
                            case 5:
                                tempGray = mainCellData.bluredbackImage[e.Y, e.X].Intensity;
                                tempBgr = new Bgr(tempGray, tempGray, tempGray);
                                break;
                            case 6:
                                tempGray = mainCellData.erasedbackImage[e.Y, e.X].Intensity;
                                tempBgr = new Bgr(tempGray, tempGray, tempGray);
                                break;
                            case 7:
                                tempGray = mainCellData.detectedImage[e.Y, e.X].Intensity;
                                tempBgr = new Bgr(tempGray, tempGray, tempGray);
                                break;
                        }
                        break;
                    }
                }

                backgroundColor = new Image<Bgr, Byte>(pictureBox_BackgroundColor.Size);
                backgroundColor.Draw(new Rectangle(new Point(0, 0), backgroundColor.Size)
                    , tempBgr, backgroundColor.Height);
                // Show background image
                this.pictureBox_BackgroundColor.Image = backgroundColor.Bitmap;
            }
        }

        private void countCellToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (mainCellData != null)
            {
                try
                {
                    int numOfCells = mainCellData.CountCell();
                    // show the results
                    if (numOfCells != -1)
                    {
                        pictureBox_Main.Image = mainCellData.detectedImage.Bitmap;
                    }
                    textBoxCellNumber.Text = string.Empty;
                    textBoxCellNumber.Text = numOfCells.ToString();
                    MessageBox.Show("Number of Cells: " + numOfCells.ToString());
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.ToString());
                }
            }
        }

        private void rgbImageToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (mainCellData != null)
            {
                try
                {
                    pictureBox_Main.Image = mainCellData.rgbImage.Bitmap;
                    button_SetBackground.Enabled &= false;
                    showedImage &= 0;
                    showedImage |= 1;
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.ToString());
                }
            }
        }

        private void grayImageToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (mainCellData != null)
            {
                try
                {
                    pictureBox_Main.Image = mainCellData.grayImage.Bitmap;
                    button_SetBackground.Enabled |= true;
                    showedImage &= 0;
                    showedImage |= 2;
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.ToString());
                }
            }
        }

        private void binaryImageToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (mainCellData != null)
            {
                try
                {
                    pictureBox_Main.Image = mainCellData.binaryImage.Bitmap;
                    button_SetBackground.Enabled &= false;
                    showedImage &= 0;
                    showedImage |= 4;
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.ToString());
                }
            }
        }

        private void edgeImageToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (mainCellData != null)
            {
                try
                {
                    pictureBox_Main.Image = mainCellData.edgeImage.Bitmap;
                    button_SetBackground.Enabled &= false;
                    showedImage &= 0;
                    showedImage |= 8;
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.ToString());
                }
            }
        }

        private void gridImageToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (mainCellData != null)
            {
                try
                {
                    pictureBox_Main.Image = mainCellData.gridImage.Bitmap;
                    button_SetBackground.Enabled &= false;
                    showedImage &= 0;
                    showedImage |= 16;
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.ToString());
                }
            }
        }

        private void bluredBackImageToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (mainCellData != null)
            {
                try
                {
                    pictureBox_Main.Image = mainCellData.bluredbackImage.Bitmap;
                    button_SetBackground.Enabled &= false;
                    showedImage &= 0;
                    showedImage |= 32;
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.ToString());
                }
            }
        }

        private void erasedBackImageToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (mainCellData != null)
            {
                try
                {
                    pictureBox_Main.Image = mainCellData.erasedbackImage.Bitmap;
                    button_SetBackground.Enabled &= false;
                    showedImage &= 0;
                    showedImage |= 64;
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.ToString());
                }
            }
        }

        private void detectedImageToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (mainCellData != null)
            {
                try
                {
                    pictureBox_Main.Image = mainCellData.detectedImage.Bitmap;
                    button_SetBackground.Enabled &= false;
                    showedImage &= 0;
                    showedImage |= 128;
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.ToString());
                }
            }
        }

        private void originalImageToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (mainCellData != null)
            {
                try
                {
                    pictureBox_Main.Image = mainCellData.originalImage.Bitmap;
                    button_SetBackground.Enabled &= false;
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.ToString());
                }
            }
        }

        private void viewToolStripMenuItem_Click(object sender, EventArgs e)
        {
            
        }

        private void viewToolStripMenuItem_DropDownOpened(object sender, EventArgs e)
        {
            //
        }

        private void button_SetBackground_Click(object sender, EventArgs e)
        {
            backgroundGrayThres = int.Parse(backgroundColor[new Point(1, 1)].Blue.ToString());
            MessageBox.Show(backgroundGrayThres.ToString());
        }

        private void classifyToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (mainCellData != null)
            {
                try
                {
                    string cellName = string.Empty;
                    CellType currentCellType = mainCellData.ClassifyCell();
                    FieldInfo fi = currentCellType.GetType().GetField(currentCellType.ToString());

                    DescriptionAttribute[] attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);

                    if (attributes != null && attributes.Length > 0)
                        cellName = attributes[0].Description;
                    else
                        cellName = currentCellType.ToString();
                    MessageBox.Show("Loại tế bào: " + cellName);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.ToString());
                }
            }
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void pictureBox_Main_MouseMove(object sender, MouseEventArgs e)
        {
            if (mainCellData != null && e.Button == MouseButtons.Left && p1.X != 0)
            {
                Byte[] tempByte = BitConverter.GetBytes(showedImage);
                BitArray tempBits = new BitArray(tempByte);
                Image<Gray, Byte> tempGray = new Image<Gray, Byte>(0, 0);
                Image<Bgr, Byte> tempBgr;
                Point t1, t2;

                for (int i = 0; i < 8; i++)
                {
                    if (tempBits[i] == true)
                    {
                        switch (i)
                        {
                            case 0:
                                tempBgr = mainCellData.rgbImage.Copy();

                                t1 = new Point(p1.X, p1.Y);
                                t2 = new Point(e.X, e.Y);

                                repairChosenArea(ref t1, ref t2);

                                tempBgr.Draw(new Rectangle(t1
                                    , new Size(Math.Abs(t2.X - t1.X), Math.Abs(t2.Y - t1.Y)))
                                    , new Bgr(0, 0, 255), 1);
                                pictureBox_Main.Image = tempBgr.Bitmap;
                                return;
                            case 1:
                                tempGray = mainCellData.grayImage.Copy();                                
                                break;
                            case 2:
                                tempGray = mainCellData.binaryImage.Copy();
                                break;
                            case 3:
                                tempGray = mainCellData.edgeImage.Copy();
                                break;
                            case 4:
                                tempGray = mainCellData.gridImage.Copy();                                
                                break;
                            case 5:
                                tempGray = mainCellData.bluredbackImage.Copy();                                
                                break;
                            case 6:
                                tempGray = mainCellData.erasedbackImage.Copy();                                
                                break;
                            case 7:
                                tempGray = mainCellData.detectedImage.Copy();                                
                                break;
                        }
                        break;
                    }
                }

                t1 = new Point(p1.X, p1.Y);
                t2 = new Point(e.X, e.Y);
                
                repairChosenArea(ref t1, ref t2);

                tempGray.Draw(new Rectangle(t1
                    , new Size(Math.Abs(t2.X - t1.X), Math.Abs(t2.Y - t1.Y)))
                    , new Gray(255.0), 1);
                
                // Show background image
                this.pictureBox_Main.Image = tempGray.Bitmap;
            }
        }

        private void pictureBox_Main_MouseDown(object sender, MouseEventArgs e)
        {
            if (mainCellData != null && e.Button == MouseButtons.Left && e.Clicks == 1)
            {
                p1.X = e.X;
                p1.Y = e.Y;
            }
        }

        private void pictureBox_Main_MouseUp(object sender, MouseEventArgs e)
        {
            if (mainCellData != null && e.Clicks == 1 && e.Button == MouseButtons.Left)
            {
                p2.X = e.X;
                p2.Y = e.Y;

                repairChosenArea(ref p1, ref p2);
            }
        }
        
        // 
        private void repairChosenArea(ref Point p1, ref Point p2)
        {
            Point temp1 = new Point();
            Point temp2 = new Point();

            // choose the start and end point of the area
            if (p1.X <= p2.X)
            {
                temp1.X = p1.X;
                temp2.X = p2.X;
            }
            else
            {
                temp1.X = p2.X;
                temp2.X = p1.X;
            }

            if (p1.Y <= p2.Y)
            {
                temp1.Y = p1.Y;
                temp2.Y = p2.Y;
            }
            else
            {
                temp1.Y = p2.Y;
                temp2.Y = p1.Y;
            }

            // validate the position
            if (temp1.X < 0)
            {
                temp1.X = 0;
            }
            if (temp1.Y < 0)
            {
                temp1.Y = 0;
            }

            if (temp2.X > pictureBox_Main.Width - 1)
            {
                temp2.X = pictureBox_Main.Width - 1;
            }
            if (temp2.Y > pictureBox_Main.Height - 1)
            {
                temp2.Y = pictureBox_Main.Height - 1;
            }

            p1 = temp1;
            p2 = temp2;
        }
        //
        private void button_CropImage_Click(object sender, EventArgs e)
        {
            if (this.pictureBox_Main.checkBox_RecSelected.CheckState == CheckState.Checked)
            {
                Point startPoint = this.pictureBox_Main.selectedRectangle.StartPoint;
                Point endPoint = this.pictureBox_Main.selectedRectangle.EndPoint;
                p1 = startPoint;
                p2 = endPoint;
                miniCellData = CellData.CopyFrom(mainCellData, new Rectangle(startPoint, new Size(endPoint.X - startPoint.X, endPoint.Y - startPoint.Y)));
            }            
        }

        private void miniCountCellToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (miniCellData != null)
            {
                try
                {
                    int numOfCells = miniCellData.CountCell();

                    if (numOfCells != -1)
                    {
                        pictureBox_Main.Image = miniCellData.detectedImage.Bitmap;
                        //Graphics g = Graphics.FromImage(pictureBox_Main.Image);
                        //g.DrawImage(miniCellData.detectedImage.Bitmap, p1);
                        //g.Dispose();
                        ////pictureBox_Main.CreateGraphics().DrawImage(miniCellData.detectedImage.Bitmap, p1);
                    }
                    textBoxCellNumber.Text = string.Empty;
                    textBoxCellNumber.Text = numOfCells.ToString();
                    MessageBox.Show("Num of Cells: " + numOfCells.ToString());
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.ToString());
                }
            }
        }
    }
}
